package com.vy.stl.interceptor;

import com.vy.stl.constants.Constants;
import com.vy.stl.entity.Admin;
import com.vy.stl.service.AdminService;
import com.vy.stl.util.JWTUtil;
import com.vy.stl.util.Result;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @create: 2025/08/21 21:18
 * @description:基于 Spring MVC HandlerInterceptor 实现的管理员身份验证与权限拦截器，核心作用是在管理员请求到达控制器（Controller）之前，通过 JWT Token 验证其登录状态和合法性，仅允许已登录且有效的管理员访问接口
 * 获取 Token → 验证 Token → 解析用户 → 判断权限 → 处理放行 / 拦截
 */
@Component  //标记为Spring组件，使其能被自动扫描和注入
@Slf4j      //自动生成日志对象log
public class AdminInterceptor implements HandlerInterceptor {

    @Autowired
    AdminService adminService;

    /**
     * 前置拦截：
     * 对管理员请求进行身份验证和权限控制，主要通过JWT Token实现
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1. 获取请求头中的token消息
        String token = request.getHeader(Constants.TOKEN);
        //2. 获取请求路径，SpringBoot会将所有不存在的路径转成/error
        String uri = request.getRequestURI();
        System.out.println("uri: " + uri);
        //声明Admin对象，存储解析token后得到的管理员信息
        Admin admin = null;
        //3. 验证token是否存在
        if (StringUtils.hasText(token)) {//判断token是否有实际内容（非null非空字符串）
            try {
                //4. 尝试解析jwt token：token字符串传到JWTUtil工具类的parseJWT方法，得到Claims对象（JWT的载荷信息，包含用户标识等信息）
                Claims claims = JWTUtil.parseJWT(token);
                //5. 从token载荷中获取手机号
                String phone = claims.getSubject();
                //6. 通过手机号查询管理员信息
                admin = adminService.getAdminByPhone(phone);
            } catch (Exception e) {
                //解析token失败（如token过期，篡改等），打印日志
                log.info("解析token失败");
            }
        }
        //7. 判断管理员信息是否存在（token解析成功且查询到有效管理员）
        if (!ObjectUtils.isEmpty(admin)) {
            //8. 重新登陆，生成新的token（延长有效期，+30分钟）
            token = JWTUtil.createJWT(admin.getPhone());
            //9. 新token设置到响应头中，返回给前端，key为Constants.TOKEN
            response.setHeader(Constants.TOKEN, token);
            return true;//拦截器放行，允许请求继续处理
        } else {
            //10. 管理员信息不存在（token无效or未查询到用户），设置响应状态码401，用户没有权限访问
            response.setStatus(Constants.STATUS_401);
            //11. 设置响应内容类型JSON，编码UTF-8
            response.setContentType("application/json;charset=utf-8");
            //12. 向响应体写入JSON格式的错误信息，返回给前端json
            response.getWriter().write(Result.error(Constants.STATUS_401,"用户未登录或登录已过期").toJson());
            return false;//拦截器不放行，终止请求处理
        }
    }
}
